﻿//Created by Action Script Viewer - http://www.buraks.com/asv
package Engine.Classes {
    import flash.events.*;
    import Engine.Interfaces.*;
    import flash.display.*;
    import flash.geom.*;
    import Engine.Helpers.*;
    import Engine.*;

    public class TileMap {

        protected static const LOT_OUTLINE_THICKNESS:Number = 1;
        protected static const LOT_OUTLINE_BORDER_THICKNESS:Number = 1;

        protected static var m_fastXOffset:int;
        protected static var m_fastYOffset:int;

        protected var m_width:int;
        protected var m_height:int;
        protected var m_drawingTarget:Object;
        protected var m_lotOutline:Sprite;					// 边界线区域
        protected var m_terrain:ITerrainMap;
        protected var m_originX:int = 0;
        protected var m_originY:int = 0;
        protected var m_oldZoom:Number = 0;
        protected var m_bitmapData:BitmapData = null;		// 重点维护这个位图数据，负责把这个数据输出到ViewPort上
        protected var m_useFast:Boolean = true;

        public function TileMap(_arg1:int, _arg2:int):void{
            this.m_lotOutline = new Sprite();
            super();
            this.m_width = _arg1;
            this.m_height = _arg2;
			
			// 清理整个ViewPort
            this.m_drawingTarget = GlobalEngine.viewport;
            this.m_drawingTarget.graphics.clear();
            while (this.m_drawingTarget.numChildren > 0) {
                this.m_drawingTarget.removeChildAt(0);
            };
			
			// 划出TileMap的边界线
            this.generateLotOutline();
            this.m_lotOutline.visible = false;
            this.m_drawingTarget.addChild(this.m_lotOutline);
			
            var _local3:Vector2 = IsoMath.tilePosToPixelPos(0, 0, 0, true);
            this.m_originX = (_local3.x - (Constants.TILE_WIDTH / 2));
            this.m_originY = (_local3.y - Constants.TILE_HEIGHT);
            m_fastXOffset = ((Constants.TILE_WIDTH / 2) / Constants.TILE_SCALE);
            m_fastYOffset = ((Constants.TILE_HEIGHT / 2) / Constants.TILE_SCALE);
        }
        public static function drawTileArea(_arg1:Object, _arg2:Point, _arg3:Point, _arg4:Point):void{
            _arg1.graphics.moveTo(_arg2.x, _arg2.y);
            _arg1.graphics.lineTo((_arg2.x + _arg3.x), (_arg2.y + _arg3.y));
            _arg1.graphics.lineTo(((_arg2.x + _arg3.x) + _arg4.x), ((_arg2.y + _arg3.y) + _arg4.y));
            _arg1.graphics.lineTo((_arg2.x + _arg4.x), (_arg2.y + _arg4.y));
            _arg1.graphics.lineTo(_arg2.x, _arg2.y);
        }

        public function setTerrain(_arg1:ITerrainMap):void{
            this.m_terrain = _arg1;
        }
        public function getTerrain():ITerrainMap{
            return (this.m_terrain);
        }
        protected function useFastSystem():Boolean{
            return (this.m_useFast);
        }
        public function render(_arg1:Viewport):void{
            var target:* = _arg1;
            if (this.m_terrain){
                if (this.useFastSystem()){
                    try {
                        this.renderFast(target);
                    } catch(err:Error) {
                        m_useFast = false;
                        renderLowMem(target);
                    };
                } else {
                    this.renderLowMem(target);
                };
            };
        }
		
		/**
		 *  负责快速的把TerrianMap里的Tile通过位图拷贝的方式复制到ViewPort里，
		 *  先生成一个张大的位图，一次拷贝过去
		 */
        protected function renderFast(_arg1:Viewport):void{
            var _local3:Tile;
            var _local4:BitmapData;
            var _local6:int;
            var _local7:int;
            var _local8:int;
            var _local9:int;
            var _local2:Number = GlobalEngine.viewport.getZoom();
            var _local5:Point = new Point(0, 0);
			
            if (((!((this.m_oldZoom == _local2))) || (this.m_terrain.isDirty()))){
                _local6 = (((this.m_width + this.m_height) * m_fastXOffset) * _local2);
                _local7 = (((this.m_width + this.m_height) * m_fastYOffset) * _local2);
				
                if (this.m_bitmapData){
                    this.m_bitmapData.dispose();
                };
				
                this.m_bitmapData = new BitmapData(_local6, _local7, false, Config.VIEWPORT_CLEAR_COLOR);
                _local7 = (_local7 - (Constants.TILE_HEIGHT * _local2));
                _local6 = (_local6 - (Constants.TILE_WIDTH * _local2));
                _local8 = 0;
                while (_local8 < this.m_height) {
                    _local5.x = ((_local6 / 2) - ((_local8 * m_fastXOffset) * _local2));
                    _local5.y = (_local7 - ((_local8 * m_fastYOffset) * _local2));
                    _local9 = 0;
                    while (_local9 < this.m_width) {
                        _local3 = (this.m_terrain.tileAt(_local9, _local8) as Tile);
                        if (_local3){
                            _local4 = _local3.getBitmapData();
                            this.m_bitmapData.copyPixels(_local4, _local4.rect, _local5, null, null, true);
                        } else {
                            GlobalEngine.log("TileMap", "TileMap tile not found");
                        };
                        _local5.x = (_local5.x + (m_fastXOffset * _local2));
                        _local5.y = (_local5.y - (m_fastYOffset * _local2));
                        _local9++;
                    };
                    _local8++;
                };
                this.m_terrain.cleanDirty();
            };
            _arg1.copyPixels(this.m_bitmapData, this.m_bitmapData.rect, new Point(0, 0), null, null, true);
            this.m_oldZoom = _local2;
        }
		
		
		/**
		 * 负责以低内存的方式把TerrianMap里的Tile通过位图拷贝的方式复制到ViewPort里，
		 * 一次拷贝一个Tile
		 * 
		 */
        protected function renderLowMem(_arg1:Viewport):void{
            var _local3:Tile;
            var _local4:BitmapData;
            var _local13:int;
            var _local2:Number = GlobalEngine.viewport.getZoom();
            var _local5:Point = new Point(0, 0);
            if (this.m_bitmapData){
                this.m_bitmapData.dispose();
                this.m_bitmapData = null;
            };
            var _local6:int = _arg1.getBitmapData().width;
            var _local7:int = _arg1.getBitmapData().height;
            var _local8:int = IsoMath.screenPosToTilePos(_local6, _local7).y;
            _local8 = ((_local8 < 0)) ? 0 : _local8;
            var _local9:int = IsoMath.screenPosToTilePos(0, _local7).x;
            _local9 = ((_local9 < 0)) ? 0 : _local9;
            var _local10:int = IsoMath.screenPosToTilePos(0, 0).y;
            _local10 = ((_local10 > this.m_height)) ? this.m_height : _local10;
            var _local11:int = IsoMath.screenPosToTilePos(_local6, 0).x;
            _local11 = ((_local11 > this.m_width)) ? this.m_width : _local11;
            var _local12:int = _local8;
            while (_local12 < _local10) {
                _local5.x = (this.m_originX - ((_local12 - _local9) * m_fastXOffset));
                _local5.y = (this.m_originY - ((_local12 + _local9) * m_fastYOffset));
                _local13 = _local9;
                while (_local13 < _local11) {
                    _local3 = (this.m_terrain.tileAt(_local13, _local12) as Tile);
                    if (_local3){
                        _local4 = _local3.getBitmapData();
                        _arg1.copyPixels(_local4, _local4.rect, _local5, null, null, true);
                    } else {
                        GlobalEngine.log("TileMap", "TileMap tile not found");
                    };
                    _local5.x = (_local5.x + m_fastXOffset);
                    _local5.y = (_local5.y - m_fastYOffset);
                    _local13++;
                };
                _local12++;
            };
            this.m_terrain.cleanDirty();
            this.m_oldZoom = _local2;
        }
        public function getReferencedAssets():Array{
            var _local3:int;
            var _local4:Tile;
            var _local1:Array = [];
            var _local2:int;
            while (_local2 < this.m_height) {
                _local3 = 0;
                while (_local3 < this.m_width) {
                    _local4 = this.m_terrain.tileAt(_local3, _local2);
                    if (_local4 != null){
                        if (_local1.indexOf(_local4) == -1){
                            _local1.push(_local4);
                        };
                    };
                    _local3++;
                };
                _local2++;
            };
            return (_local1);
        }
        public function setLotOutlineVisible(_arg1:Boolean):void{
            this.m_lotOutline.visible = _arg1;
        }
        public function isLotOutlineVisible():Boolean{
            return (this.m_lotOutline.visible);
        }
        private function generateLotOutline():void{
            var _local1:Point = IsoMath.tilePosToPixelPos(0, 0, 0, true);
            var _local2:Point = IsoMath.getPixelDeltaFromTileDelta(this.m_width, 0, true);
            var _local3:Point = IsoMath.getPixelDeltaFromTileDelta(0, this.m_height, true);
            this.m_lotOutline.graphics.clear();
            this.m_lotOutline.graphics.moveTo(_local1.x, _local1.y);
            this.m_lotOutline.graphics.lineStyle((TileMap.LOT_OUTLINE_THICKNESS + (2 * TileMap.LOT_OUTLINE_BORDER_THICKNESS)), Constants.COLOR_LOT_OUTLINE_BORDER, Constants.ALPHA_LOT_OUTLINE_BORDER);
            drawTileArea(this.m_lotOutline, _local1, _local2, _local3);
            this.m_lotOutline.graphics.lineStyle(0, 0);
            this.m_lotOutline.graphics.moveTo(_local1.x, _local1.y);
            this.m_lotOutline.graphics.lineStyle(TileMap.LOT_OUTLINE_THICKNESS, Constants.COLOR_LOT_OUTLINE, Constants.ALPHA_LOT_OUTLINE);
            drawTileArea(this.m_lotOutline, _local1, _local2, _local3);
            this.m_lotOutline.graphics.lineStyle(0, 0);
        }
        public function floodFill(_arg1:int, _arg2:int, _arg3:Tile):void{
            var _local8:IntVector2;
            var _local9:int;
            var _local4:Array = new Array();
            var _local5:Tile = this.getTileForPosition(_arg1, _arg2);
            var _local6:Boolean;
            var _local7:Boolean;
            if (_local5 != _arg3){
                _local4.push(new IntVector2(_arg1, _arg2));
                while (_local4.length) {
                    _local8 = (_local4.pop() as IntVector2);
                    _local9 = _local8.y;
                    while (this.getTileForPosition(_local8.x, _local9) == _local5) {
                        _local9--;
                    };
                    _local9++;
                    _local7 = false;
                    _local6 = false;
                    while (this.getTileForPosition(_local8.x, _local9) == _local5) {
                        this.m_terrain.setTile(_local8.x, _local9, _arg3);
                        if (((!(_local6)) && ((this.getTileForPosition((_local8.x - 1), _local9) == _local5)))){
                            _local4.push(new IntVector2((_local8.x - 1), _local9));
                            _local6 = true;
                        } else {
                            if (((_local6) && (!((this.getTileForPosition((_local8.x - 1), _local9) == _local5))))){
                                _local6 = false;
                            };
                        };
                        if (((!(_local7)) && ((this.getTileForPosition((_local8.x + 1), _local9) == _local5)))){
                            _local4.push(new IntVector2((_local8.x + 1), _local9));
                            _local7 = true;
                        } else {
                            if (((_local7) && (!((this.getTileForPosition((_local8.x + 1), _local9) == _local5))))){
                                _local7 = false;
                            };
                        };
                        _local9++;
                    };
                };
                this.fullyRedrawTileMap();
            };
        }
        public function getWidth():int{
            return (this.m_width);
        }
        public function getHeight():int{
            return (this.m_height);
        }
        public function getTileForPosition(_arg1:int, _arg2:int):Tile{
            var _local3:Tile;
            if ((((((((_arg1 >= 0)) && ((_arg1 < this.m_width)))) && ((_arg2 >= 0)))) && ((_arg2 < this.m_height)))){
                _local3 = this.m_terrain.tileAt(_arg1, _arg2);
            };
            return (_local3);
        }
        public function fullyRedrawTileMap():void{
            this.m_drawingTarget.graphics.clear();
            this.generateLotOutline();
        }

    }
}//package Engine.Classes 
